﻿using System;
using System.Collections.Generic;
using System.Drawing;

using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;


namespace Client
{
    public sealed class DrawScreen : IDisposable
    {
        public static readonly DrawScreen Me = new DrawScreen();

        const int MaxWidth = 400;
        const int MaxHeight = 200;
        const int MaxSysMsg = 10;
        //const int FrameTime = 5;

        private int CurrDelay;
        private List<string> MsgList;

        private List<string> HintList;
        private int HintX, HintY, HintWidth, HintHeight;
        private bool HintUp;
        private Color HintColor;
        private Color TextColor;
        private Texture HintBack;

        private DrawScreen()
            : base()
        {
            MsgList = new List<string>();
            CurrDelay = 0;

            HintList = new List<string>();
            HintBack = null;
        }

        public void Initialize()
        {
            // Create texture - NOTE: we will stretch it bigger than 1 x 1!
            HintBack = new Texture(DirectX.Me.DirectXDevice, 1, 1, 1,
                Usage.None, Format.A8R8G8B8, Pool.Managed);

            // Fill with colour.
            GraphicsStream Stream = HintBack.LockRectangle(0, LockFlags.None);
            Stream.Write(Color.White.ToArgb());
            HintBack.UnlockRectangle(0);
        }

        public void ClearHint()
        {
            HintList.Clear();
        }

        public void ClearScreen()
        {
            MsgList.Clear();
            HintList.Clear();
        }

        public void ShowHint(int x, int y, string str, Color hcolor, Color tcolor, bool drawup)
        {
            int w;
            Rectangle rcPos;
            string data;

            if (string.IsNullOrEmpty(str))
                return;

            string[] lines = str.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);

            if (lines.Length > 0)
            {
                ClearHint();
                HintX = x;
                HintY = y;
                HintWidth = 0;
                HintHeight = 0;
                HintUp = drawup;
                HintColor = hcolor;
                TextColor = tcolor;

                for (int i = 0; i < lines.Length; i++)
                {
                    data = lines[i];

                    rcPos = DirectText.Me.MeasureString(data);
                    w = rcPos.Width + 4/*¿©¹é*/ * 2;
                    if (w > HintWidth)
                        HintWidth = w;
                    if (data != String.Empty)
                        HintList.Add(data);
                }
            }

            rcPos = DirectText.Me.MeasureString("A");
            HintHeight = (rcPos.Height + 1) * HintList.Count + 3/*¿©¹é*/ * 2;
            if (HintUp)
                HintY -= HintHeight;
        }

        public void AddSysMsg(string str)
        {
            while (MsgList.Count >= MaxSysMsg)
                MsgList.RemoveAt(0);

            MsgList.Add(str);
            CurrDelay = 0;
        }

        private void ShowSysMsg(int gameTime, int posX, int posY)
        {
            CurrDelay += gameTime;

            for (int i = 0; i < MsgList.Count; i++)
            {
                string msg = MsgList[i];
                if (string.IsNullOrEmpty(msg)) continue;

                DirectText.Me.DrawShadowText(msg, posX, posY + i * 15, Color.FromArgb(10, 10, 10), Color.FromArgb(100, 200, 100));
            }

            int delayTime = 3000;
            if (MsgList.Count > 5)
                delayTime = 1000;

            if (CurrDelay > delayTime)
            {
                if (MsgList.Count > 0)
                    MsgList.RemoveAt(0);

                CurrDelay = 0;
            }
        }

        public void Render(int gameTime)
        {
            ShowSysMsg(gameTime, 30, 40);

            int i, hx = 0, hy = 0;
            bool dohint = false;

            if (HintList.Count > 0)
            {
                if (HintBack != null)
                {
                    if (HintWidth > MaxWidth)
                        HintWidth = MaxWidth;
                    if (HintHeight > MaxHeight)
                        HintHeight = MaxHeight;
                    if (HintX + HintWidth > ClientGlobals.ScreenWidth)
                        hx = ClientGlobals.ScreenWidth - HintWidth;
                    else
                        hx = HintX;
                    if (HintY < 0)
                        hy = 0;
                    else
                        hy = HintY;
                    if (hx < 0)
                        hx = 0;

                    DirectX.Me.GameSprite.Draw(HintBack, new Rectangle(0, 0, HintWidth, HintHeight),
                        Vector3.Empty, new Vector3(hx, hy, 0), Color.FromArgb(130, TextColor));

                    dohint = true;
                }

                if (dohint)
                {
                    Rectangle rcPos = DirectText.Me.MeasureString("A");
                    for (i = 0; i < HintList.Count; i++)
                        DirectText.Me.DrawText(HintList[i], hx + 4, hy + 3 + (rcPos.Height + 1) * i, HintColor);
                }
            }
        }

        #region "IDisposable Support"
        private bool disposedValue;      // To detect redundant calls

        private void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: dispose managed state (managed objects).
                    // Free other state (managed objects).
                    if (HintBack != null && !HintBack.Disposed)
                    {
                        HintBack.Dispose();
                        HintBack = null;
                    }
                }

                // TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
                // TODO: set large fields to null.
                HintList.Clear();
                HintList = null;
                MsgList.Clear();
                MsgList = null;
                disposedValue = true;
            }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        #endregion
    }
}